package cn.edu.tju.elm.controller;

import cn.edu.tju.core.model.HttpResult;
import cn.edu.tju.core.model.ResultCodeEnum;
import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.core.security.PermissionUtils;
import cn.edu.tju.elm.dto.StarCreateDTO;
import cn.edu.tju.elm.dto.StarResponseDTO;
import cn.edu.tju.elm.dto.StarUpdateDTO;
import cn.edu.tju.elm.mapper.StarMapper;
import cn.edu.tju.elm.model.Star;
import cn.edu.tju.elm.service.StarService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * ClassName: StarController
 * Package: cn.edu.tju.elm.controller
 * Description:
 *
 * @Author Niu Wenhang
 * @Create 2025/9/19 2:58
 * @Version 1.0
 * 
 * 
 * @Author Liu Wenrui
 * @Create 2025/9/24 15:00
 * @Version 1.1
 */
@RestController
@RequestMapping("/api/star")
@Tag(name = "管理收藏")
public class StarController {
    @Autowired
    private StarService starService;

    @Autowired
    private UserService userService;

    @Autowired
    private StarMapper starMapper;

    @Autowired
    private PermissionUtils permissionUtils;

    @GetMapping("")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "查询当前用户收藏店铺")
    public HttpResult<List<StarResponseDTO>> getStars() {
        try {
            User user = userService.getUserWithAuthorities().get();
            List<Star> stars = starService.getStarsByUserId(user.getId());
            List<StarResponseDTO> responseDTOs = starMapper.starsToResponseDTOs(stars);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询收藏失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessStarData(@starService.getStarById(#id).get().getUser().getId())")
    @Operation(summary = "根据收藏ID查询收藏")
    public HttpResult<StarResponseDTO> getStarById(@PathVariable Long id) {
        try {
            Optional<Star> star = starService.getStarById(id);
            if (star.isPresent()) {
                StarResponseDTO responseDTO = starMapper.starToResponseDTO(star.get());
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "收藏不存在");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询收藏失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-business/{businessId}")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "根据店铺ID查询收藏")
    public HttpResult<StarResponseDTO> getStarByBusinessId(@PathVariable Long businessId) {
        try {
            User user = userService.getUserWithAuthorities().get();
            Optional<Star> star = starService.getStarByUserIdAndBusinessId(user.getId(), businessId);
            if (star.isPresent()) {
                StarResponseDTO responseDTO = starMapper.starToResponseDTO(star.get());
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "未收藏该店铺");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询收藏失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/{businessId}")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "检查是否已收藏店铺")
    public HttpResult<Boolean> checkStarExists(@PathVariable Long businessId) {
        try {
            User user = userService.getUserWithAuthorities().get();
            boolean exists = starService.checkStarExists(user.getId(), businessId);
            return HttpResult.success(exists);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "检查收藏状态失败: " + e.getMessage());
        }
    }

    @GetMapping("/recent")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "查询最近的收藏")
    public HttpResult<List<StarResponseDTO>> getRecentStars(@RequestParam(defaultValue = "10") Integer limit) {
        try {
            User user = userService.getUserWithAuthorities().get();
            List<Star> stars = starService.getRecentStarsByUserId(user.getId(), limit);
            List<StarResponseDTO> responseDTOs = starMapper.starsToResponseDTOs(stars);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询最近收藏失败: " + e.getMessage());
        }
    }

    @GetMapping("/count")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "查询收藏数量")
    public HttpResult<Long> getStarCount() {
        try {
            User user = userService.getUserWithAuthorities().get();
            Long count = starService.getStarCountByUserId(user.getId());
            return HttpResult.success(count);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询收藏数量失败: " + e.getMessage());
        }
    }

    @PostMapping("")
    @PreAuthorize("hasAnyAuthority('ADMIN','BUSINESS','USER')")
    @Operation(summary = "收藏店铺")
    public HttpResult<StarResponseDTO> addStar(@RequestBody StarCreateDTO starCreateDTO) {
        try {
            Star star = starMapper.createDtoToStar(starCreateDTO);
            User user = userService.getUserWithAuthorities().get();
            LocalDateTime now = LocalDateTime.now();
            star.setCreator(user.getId());
            star.setUser(user);
            star.setCreateTime(now);
            star.setUpdater(user.getId());
            star.setUpdateTime(now);
            star.setDeleted(false);
            Star s = starService.addStar(star);
            return HttpResult.success(starMapper.starToResponseDTO(s));
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "收藏店铺失败: " + e.getMessage());
        }
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessStarData(@starService.getStarById(#id).get().getUser().getId())")
    @Operation(summary = "修改收藏")
    public HttpResult<StarResponseDTO> updateStar(@PathVariable("id") Long id, @RequestBody StarUpdateDTO starUpdateDTO){
        try {
            User user = userService.getUserWithAuthorities().get();
            Star star = starMapper.updateDtoToStar(starUpdateDTO);
            star.setId(id);
            star.setUpdater(user.getId());
            star.setUpdateTime(LocalDateTime.now());
            Star updatedStar = starService.updateStar(star);
            StarResponseDTO responseDTO = starMapper.starToResponseDTO(updatedStar);
            return HttpResult.success(responseDTO);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "修改收藏失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessStarData(@starService.getStarById(#id).get().getUser().getId())")
    @Operation(summary = "删除收藏")
    public HttpResult<String> deleteStar(@PathVariable("id") Long id){
        try {
            starService.deleteStar(id);
            return HttpResult.success("删除成功");
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "删除收藏失败: " + e.getMessage());
        }
    }

    @PatchMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessStarData(@starService.getStarById(#id).get().getUser().getId())")
    @Operation(summary = "部分修改收藏信息")
    public HttpResult<StarResponseDTO> partialUpdateStar(@PathVariable("id") Long id, @RequestBody StarUpdateDTO starUpdateDTO){
        try {
            User user = userService.getUserWithAuthorities().get();
            Optional<Star> existingStar = starService.getStarById(id);
            if (existingStar.isPresent()) {
                Star starToUpdate = existingStar.get();
                // 只更新非空字段
                if (starUpdateDTO.getBusinessId() != null) {
                    Star updateData = starMapper.updateDtoToStar(starUpdateDTO);
                    starToUpdate.setBusiness(updateData.getBusiness());
                }
                if (starUpdateDTO.getUserId() != null) {
                    Star updateData = starMapper.updateDtoToStar(starUpdateDTO);
                    starToUpdate.setUser(updateData.getUser());
                }
                if (starUpdateDTO.getDeleted() != null) {
                    starToUpdate.setDeleted(starUpdateDTO.getDeleted());
                }
                starToUpdate.setUpdater(user.getId());
                starToUpdate.setUpdateTime(LocalDateTime.now());
                Star updatedStar = starService.updateStar(starToUpdate);
                StarResponseDTO responseDTO = starMapper.starToResponseDTO(updatedStar);
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "收藏不存在");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "部分修改收藏失败: " + e.getMessage());
        }
    }
}
